import { BaseModel } from './BaseModel';
import { query } from '../../config/database';

export interface IFolder {
  id: string;
  name: string;
  parent_id?: string;
  path: string;
  created_at: Date;
  created_by?: string;
}

export class Folder extends BaseModel {
  constructor() {
    super('folders');
  }
  
  // 创建文件夹
  async createFolder(folderData: {
    name: string;
    parent_id?: string;
    created_by?: string;
  }): Promise<IFolder> {
    // 计算完整路径
    const path = await this.calculatePath(folderData.name, folderData.parent_id);
    
    const result = await query(
      `INSERT INTO folders (name, parent_id, path, created_by)
       VALUES ($1, $2, $3, $4)
       RETURNING *`,
      [folderData.name, folderData.parent_id, path, folderData.created_by]
    );
    return result.rows[0];
  }
  
  // 获取文件夹树结构
  async getFolderTree(): Promise<any[]> {
    const result = await query(
      `WITH RECURSIVE folder_tree AS (
        SELECT id, name, parent_id, path, created_at, created_by, 0 as level
        FROM folders 
        WHERE parent_id IS NULL
        
        UNION ALL
        
        SELECT f.id, f.name, f.parent_id, f.path, f.created_at, f.created_by, ft.level + 1
        FROM folders f
        INNER JOIN folder_tree ft ON f.parent_id = ft.id
      )
      SELECT * FROM folder_tree ORDER BY level, name ASC`
    );
    
    return this.buildTree(result.rows);
  }
  
  // 获取子文件夹
  async getChildFolders(parentId?: string): Promise<IFolder[]> {
    let sql = 'SELECT * FROM folders WHERE ';
    const params: any[] = [];
    
    if (parentId) {
      sql += 'parent_id = $1';
      params.push(parentId);
    } else {
      sql += 'parent_id IS NULL';
    }
    
    sql += ' ORDER BY name ASC';
    
    const result = await query(sql, params);
    return result.rows;
  }
  
  // 获取文件夹及其所有子文件夹的ID
  async getFolderAndDescendantIds(folderId: string): Promise<string[]> {
    const result = await query(
      `WITH RECURSIVE folder_descendants AS (
        SELECT id FROM folders WHERE id = $1
        
        UNION ALL
        
        SELECT f.id
        FROM folders f
        INNER JOIN folder_descendants fd ON f.parent_id = fd.id
      )
      SELECT id FROM folder_descendants`,
      [folderId]
    );
    
    return result.rows.map((row: any) => row.id);
  }
  
  // 移动文件夹
  async moveFolder(id: string, newParentId?: string): Promise<IFolder | null> {
    // 检查是否会造成循环引用
    if (newParentId && await this.wouldCreateCycle(id, newParentId)) {
      throw new Error('无法移动文件夹：会造成循环引用');
    }
    
    // 获取当前文件夹信息
    const currentFolder = await this.findById(id);
    if (!currentFolder) {
      return null;
    }
    
    // 计算新路径
    const newPath = await this.calculatePath(currentFolder.name, newParentId);
    
    const result = await query(
      `UPDATE folders 
       SET parent_id = $2, path = $3
       WHERE id = $1
       RETURNING *`,
      [id, newParentId, newPath]
    );
    
    // 更新所有子文件夹的路径
    await this.updateDescendantPaths(id);
    
    return result.rows[0] || null;
  }
  
  // 重命名文件夹
  async renameFolder(id: string, newName: string): Promise<IFolder | null> {
    const currentFolder = await this.findById(id);
    if (!currentFolder) {
      return null;
    }
    
    // 检查同级文件夹名称是否重复
    if (!await this.isNameUniqueInParent(newName, currentFolder.parent_id, id)) {
      throw new Error('同级目录下已存在相同名称的文件夹');
    }
    
    // 计算新路径
    const newPath = await this.calculatePath(newName, currentFolder.parent_id);
    
    const result = await query(
      `UPDATE folders 
       SET name = $2, path = $3
       WHERE id = $1
       RETURNING *`,
      [id, newName, newPath]
    );
    
    // 更新所有子文件夹的路径
    await this.updateDescendantPaths(id);
    
    return result.rows[0] || null;
  }
  
  // 删除文件夹（级联删除子文件夹和脚本）
  async deleteFolder(id: string): Promise<boolean> {
    // 获取所有子文件夹ID
    const descendantIds = await this.getFolderAndDescendantIds(id);
    
    // 删除所有相关脚本
    await query(
      `DELETE FROM scripts WHERE folder_id = ANY($1)`,
      [descendantIds]
    );
    
    // 删除所有文件夹
    const result = await query(
      `DELETE FROM folders WHERE id = ANY($1)`,
      [descendantIds]
    );
    
    return result.rowCount > 0;
  }
  
  // 检查文件夹名称在同级目录下是否唯一
  async isNameUniqueInParent(name: string, parentId?: string, excludeId?: string): Promise<boolean> {
    let sql = 'SELECT 1 FROM folders WHERE name = $1';
    const params: any[] = [name];
    let paramIndex = 2;
    
    if (parentId) {
      sql += ` AND parent_id = $${paramIndex++}`;
      params.push(parentId);
    } else {
      sql += ` AND parent_id IS NULL`;
    }
    
    if (excludeId) {
      sql += ` AND id != $${paramIndex++}`;
      params.push(excludeId);
    }
    
    const result = await query(sql, params);
    return result.rows.length === 0;
  }
  
  // 获取文件夹统计信息
  async getFolderStats(id: string): Promise<{
    total_scripts: number;
    total_subfolders: number;
    total_size: number; // 脚本内容总长度
  }> {
    const descendantIds = await this.getFolderAndDescendantIds(id);
    
    const result = await query(
      `SELECT 
        COUNT(DISTINCT s.id) as total_scripts,
        COUNT(DISTINCT f.id) - 1 as total_subfolders,
        SUM(LENGTH(COALESCE(s.content, ''))) as total_size
       FROM folders f
       LEFT JOIN scripts s ON s.folder_id = f.id
       WHERE f.id = ANY($1)`,
      [descendantIds]
    );
    
    const stats = result.rows[0];
    return {
      total_scripts: parseInt(stats.total_scripts, 10),
      total_subfolders: parseInt(stats.total_subfolders, 10),
      total_size: parseInt(stats.total_size, 10) || 0
    };
  }
  
  // 计算文件夹路径
  private async calculatePath(name: string, parentId?: string): Promise<string> {
    if (!parentId) {
      return `/${name}`;
    }
    
    const parent = await this.findById(parentId);
    if (!parent) {
      throw new Error('父文件夹不存在');
    }
    
    return `${parent.path}/${name}`;
  }
  
  // 检查是否会造成循环引用
  private async wouldCreateCycle(folderId: string, newParentId: string): Promise<boolean> {
    const descendantIds = await this.getFolderAndDescendantIds(folderId);
    return descendantIds.includes(newParentId);
  }
  
  // 更新子文件夹路径
  private async updateDescendantPaths(folderId: string): Promise<void> {
    await query(
      `WITH RECURSIVE folder_update AS (
        SELECT id, name, parent_id, 
               CASE 
                 WHEN parent_id IS NULL THEN '/' || name
                 ELSE (SELECT path FROM folders WHERE id = f.parent_id) || '/' || name
               END as new_path
        FROM folders f
        WHERE parent_id = $1
        
        UNION ALL
        
        SELECT f.id, f.name, f.parent_id,
               fu.new_path || '/' || f.name as new_path
        FROM folders f
        INNER JOIN folder_update fu ON f.parent_id = fu.id
      )
      UPDATE folders 
      SET path = folder_update.new_path
      FROM folder_update
      WHERE folders.id = folder_update.id`,
      [folderId]
    );
  }
  
  // 构建树形结构
  private buildTree(flatList: any[]): any[] {
    const tree: any[] = [];
    const lookup: { [key: string]: any } = {};
    
    // 创建查找表
    flatList.forEach(item => {
      lookup[item.id] = { ...item, children: [] };
    });
    
    // 构建树形结构
    flatList.forEach(item => {
      if (item.parent_id) {
        if (lookup[item.parent_id]) {
          lookup[item.parent_id].children.push(lookup[item.id]);
        }
      } else {
        tree.push(lookup[item.id]);
      }
    });
    
    return tree;
  }
}